今天要來學習的是DOM的事件傳遞機制
這邊有一個簡單的html範例
<body class="bod">
<div class="one">
<div class="two">
<div class="three">
</div>
</div>
</div>
<body>
首先,要幫這三個<div>
加上事件監聽器
const divs = document.querySelectorAll('div');
function logText(e) {
console.log(this.classList.value);
}
divs.forEach(div => div.addEventListener('click', logText);
每當點擊<div>
的時候,要印出<div>
的class
接下來,點擊class為three的<div>
咦?怎麼印出三個class
這是因為當我們點擊第三層<div>
,我們同時也點擊到第二層跟第一層,因為它們是一層一層包起來的
這邊我作了一個簡單的示意圖
當我們點擊一個元素時,瀏覽器會從DOM的根向下捕捉(Capture),一直到我們點擊的元素為止,然後進入冒泡階段(Bubbling Phase)
接續捕捉階段,冒泡階段會從我們點擊的元素開始,向上觸發事件,以今天的範例為例,當我們點擊(click)第三層後,點擊事件會依序向上發動,所以第二層跟第一層也會被觸發
接下來,讓我們仔細看一下addEventListener()
,addEventListener()
可以傳入三個參數
type
事件種類,e.g. click, mouseenter, keydown, etc.
可參考:Event reference
listener
當指定類型的事件發生時,接收通知的對象
options
監聽對象的事件監聽器特徵
capture
如果設為true,事件會在捕捉階段觸發listener,預設false
once
如果設為true,在觸發監聽事件後,事件監聽器會被移除
passive
如果為true,則表示監聽器指定的函數(listener)將永遠不會調用preventDefault()
divs.forEach(div => div.addEventListener('click', logText, {
capture: true,
once: false
}));
那麼要如何阻止事件傳遞呢?
function logText(e) {
console.log(this.classList.value);
e.stopPropagation(); // stop bubbling!
}
這邊可以使用stopPropagation()
Event.stopPropagation()
此方法可阻止當前事件繼續進行捕捉(capturing)及冒泡(bubbling)階段的傳遞